home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / prsr_lib / iritprs1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-08  |  62.2 KB  |  1,659 lines

  1. /*****************************************************************************
  2. * Generic parser for the "Irit" solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Sep. 1991   *
  5. *****************************************************************************/
  6.  
  7. #ifdef USE_VARARGS
  8. #include <varargs.h>
  9. #else
  10. #include <stdarg.h>
  11. #endif /* USE_VARARGS */
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include <setjmp.h>
  18. #include "irit_sm.h"
  19. #include "prsr_loc.h"
  20. #include "allocate.h"
  21. #include "attribut.h"
  22. #include "irit_soc.h"
  23.  
  24. #ifdef __WINNT__
  25. #include <fcntl.h>
  26. #include <io.h>
  27. #endif /* __WINNT__ */
  28.  
  29. #if defined(AMIGA) && defined(__SASC)
  30. #include "popen.h"
  31. #endif
  32.  
  33. IPStreamInfoStruct _IPStream[MAX_NUM_OF_STREAMS];
  34.  
  35. static int
  36.     GlblFlattenObjects = TRUE;       /* If input list hierarchy is to be kept. */
  37.  
  38. static IPObjectStruct *EliminateDegenLists(IPObjectStruct *PObj);
  39. static int InputGetC(int Handler);
  40. static int InputEOF(int Handler);
  41. static int GetStringToken(int Handler, char *StringToken, int *Quoted);
  42. static void GetVertexAttributes(IPVertexStruct *PVertex, int Handler);
  43. static void GetPolygonAttributes(IPPolygonStruct *PPolygon,
  44.                  int Handler);
  45. static void GetObjectAttributes(IPObjectStruct *PObject, int Handler);
  46. static void GetGenericAttribute(IPAttributeStruct **Attrs,
  47.                 int Handler,
  48.                 char *Name);
  49. static void GetPointData(int Handler,
  50.              IPPolygonStruct *PPolygon,
  51.              int IsPolygon);
  52. static void IritPrsrGetAllObjects(int Handler,
  53.                   IPObjectStruct *PObjParent,
  54.                   int Level);
  55. static void GetNumericToken(int Handler, RealType *r);
  56. static void IritPrsrGetAuxObject(int Handler, IPObjectStruct *PObj);
  57. static int FindFileHandler(void);
  58.  
  59. /*****************************************************************************
  60. * DESCRIPTION:                                                               M
  61. * Open a data file for read/write.                         M
  62. *   Data file can be either Ascii IRIT data file or binary IRIT data file.   M
  63. *   A binary data file must have a ".bdt" (for Binary DaTa) file type.       M
  64. *   Under unix, file names with the psotfix ".Z" are assumed compressed and  M
  65. * treated accordingly.                                 M
  66. *   See also functions IritPrsrSetPolyListCirc, IritPrsrSetFlattenObjects,   M
  67. * and IritPrsrSetReadOneObject.                             M
  68. *                                                                            *
  69. * PARAMETERS:                                                                M
  70. *   FileName:   To try and open.                                             M
  71. *   Read:       If TRUE assume a read operation, otheriwse write.            M
  72. *   Messages:   Do we want error/warning messages to stderr?                 M
  73. *                                                                            *
  74. * RETURN VALUE:                                                              M
  75. *   int:        A handler to the open file, -1 if error.             M
  76. *                                                                            *
  77. * KEYWORDS:                                                                  M
  78. *   IritPrsrOpenDataFile, files, parser                                      M
  79. *****************************************************************************/
  80. int IritPrsrOpenDataFile(char *FileName, int Read, int Messages)
  81. {
  82.     FILE *f;
  83.     int ReadWriteBinary = IritPrsrSenseBinaryFile(FileName),
  84.     IsPipe = FALSE;
  85.     char *p;
  86.  
  87.     if (Read) {
  88.     if (strcmp(FileName, "-") == 0) {
  89.         f = stdin;
  90.     }
  91. #if defined(__UNIX__) || defined(OS2GCC)
  92.     else if ((p = strrchr(FileName, '.')) != NULL &&
  93.          strcmp(p, ".Z") == 0) {
  94.         char Cmd[LINE_LEN];
  95.  
  96.         sprintf(Cmd, "zcat %s", FileName);
  97.         f = popen(Cmd, "r");
  98.         IsPipe = TRUE;
  99.     }
  100. #endif /* __UNIX__ || OS2GCC */
  101.     else {
  102.         if ((f = fopen(FileName, "r")) == NULL) {
  103.         if (Messages)
  104.             fprintf(stderr, "Can't open data file %s.\n", FileName);
  105.         return -1;
  106.         }
  107.     }
  108.     }
  109.     else { /* Write */
  110.     if (strcmp(FileName, "-") == 0) {
  111.         f = stdout;
  112.     }
  113. #if defined(__UNIX__) || defined(OS2GCC)
  114.     else if ((p = strrchr(FileName, '.')) != NULL &&
  115.          strcmp(p, ".Z") == 0) {
  116.         char Cmd[LINE_LEN];
  117.  
  118.         sprintf(Cmd, "compress > %s", FileName);
  119.         f = popen(Cmd, "w");
  120.         IsPipe = TRUE;
  121.     }
  122. #endif /* __UNIX__ || OS2GCC */
  123.     else {
  124.         if ((f = fopen(FileName, "w")) == NULL) {
  125.         if (Messages)
  126.             fprintf(stderr, "Can't open data file %s.\n", FileName);
  127.         return -1;
  128.         }
  129.     }
  130.     }
  131.  
  132. #if defined(__OS2GCC__)
  133.     if (ReadWriteBinary)
  134.     setmode(FileHandle, O_BINARY);    /* Make sure it is in binary mode. */
  135. #endif /* __OS2GCC__ */
  136. #if defined(__WINNT__)
  137.     if (ReadWriteBinary)
  138.     _setmode(_fileno(f), _O_BINARY);  /* Make sure it is in binary mode. */
  139. #endif /* __WINNT__ */
  140.  
  141.     return IritPrsrOpenStreamFromFile(f, Read, ReadWriteBinary, IsPipe);
  142. }
  143.  
  144. /*****************************************************************************
  145. * DESCRIPTION:                                                               M
  146. *   Senses if a given file (name) is a binary or a text file.                M
  147. *                                                                            *
  148. * PARAMETERS:                                                                M
  149. *   FileName:  File to sense.                                                M
  150. *                                                                            *
  151. * RETURN VALUE:                                                              M
  152. *   int:       TRUE if binary, FALSE if text.                                M
  153. *                                                                            *
  154. * KEYWORDS:                                                                  M
  155. *   IritPrsrSenseBinaryFile                                                  M
  156. *****************************************************************************/
  157. int IritPrsrSenseBinaryFile(char *FileName)
  158. {
  159.     return strstr(FileName, ".bdt") || strstr(FileName, ".BDT");
  160. }
  161.  
  162. /*****************************************************************************
  163. * DESCRIPTION:                                                               M
  164. * Close a data file for read/write.                         M
  165. *                                                                            *
  166. * PARAMETERS:                                                                M
  167. *   Handler:     A handler to the open stream.                     M
  168. *   Free:     If TURE, release content.                       M
  169. *                                                                            *
  170. * RETURN VALUE:                                                              M
  171. *   void                                                                     M
  172. *                                                                            *
  173. * KEYWORDS:                                                                  M
  174. *   IritPrsrCloseStream, files, stream, parser                               M
  175. *****************************************************************************/
  176. void IritPrsrCloseStream(int Handler, int Free)
  177. {
  178.     if (Handler >= 0 && Handler < MAX_NUM_OF_STREAMS) {
  179.     if (Free) {
  180.         if (_IPStream[Handler].f != NULL) {
  181. #ifdef __UNIX__
  182.         if (_IPStream[Handler].IsPipe)
  183.             pclose(_IPStream[Handler].f);
  184.         else
  185. #endif /* __UNIX__ */
  186.             if (_IPStream[Handler].f != stdin &&
  187.             _IPStream[Handler].f != stdout &&
  188.             _IPStream[Handler].f != stderr)
  189.             fclose(_IPStream[Handler].f);
  190.         }
  191.  
  192.         if (_IPStream[Handler].CommuSoc) {
  193.         if (_IPStream[Handler].Read)
  194.             SocClientCloseSocket(Handler);
  195.         else
  196.             SocServerCloseSocket(Handler);
  197.         }
  198.     }
  199.     _IPStream[Handler].InUse = FALSE;
  200.     }
  201. }
  202.  
  203. /*****************************************************************************
  204. * DESCRIPTION:                                                               M
  205. *   Converts an open file into a stream.                                     M
  206. *                                                                            *
  207. * PARAMETERS:                                                                M
  208. *   f:         A handle to the open file.                                    M
  209. *   Read:      TRUE for reading from f, FALSE for writing to f.              M
  210. *   IsBinary:  Is it a binary file?                                          M
  211. *   IsPipe:    Is it a pipe?                                                 M
  212. *                                                                            *
  213. * RETURN VALUE:                                                              M
  214. *   int:       A handle on the constructed stream.                           M
  215. *                                                                            *
  216. * KEYWORDS:                                                                  M
  217. *   IritPrsrOpenStreamFromFile                                               M
  218. *****************************************************************************/
  219. int IritPrsrOpenStreamFromFile(FILE *f, int Read, int IsBinary, int IsPipe)
  220. {
  221.     int Handler = FindFileHandler();
  222.  
  223.     if (Handler >= 0) {
  224.     _IPStream[Handler].f = f;
  225.     _IPStream[Handler].Read = Read;
  226.     _IPStream[Handler].IsBinary = IsBinary;
  227.     _IPStream[Handler].IsPipe = IsPipe;
  228.     }
  229.  
  230.     return Handler;
  231. }
  232.  
  233. /*****************************************************************************
  234. * DESCRIPTION:                                                               M
  235. *   Converts an open socket into a stream.                                   M
  236. *                                                                            *
  237. * PARAMETERS:                                                                M
  238. *   Soc:       A handle to the open socket.                                  M
  239. *   Read:      TRUE for reading from f, FALSE for writing to f.              M
  240. *   IsBinary:  Is it a binary file?                                          M
  241. *                                                                            *
  242. * RETURN VALUE:                                                              M
  243. *   int:       A handle on the constructed stream.                           M
  244. *                                                                            *
  245. * KEYWORDS:                                                                  M
  246. *   IritPrsrOpenStreamFromSocket                                             M
  247. *****************************************************************************/
  248. int IritPrsrOpenStreamFromSocket(int Soc, int Read, int IsBinary)
  249. {
  250.     int Handler = FindFileHandler();
  251.  
  252.     if (Handler >= 0) {
  253.     _IPStream[Handler].f = NULL;
  254.     _IPStream[Handler].CommuSoc = Soc;
  255.     _IPStream[Handler].IsBinary = IsBinary;
  256.     _IPStream[Handler].Read = Read;
  257.     }
  258.  
  259.     return Handler;
  260. }
  261.  
  262. /*****************************************************************************
  263. * DESCRIPTION:                                                               *
  264. *   Searches and returns a free Open File handler.                           *
  265. *                                                                            *
  266. * PARAMETERS:                                                                *
  267. *   None                                                                     *
  268. *                                                                            *
  269. * RETURN VALUE:                                                              *
  270. *   int:     Free handler, or -1 if none found.                              *
  271. *****************************************************************************/
  272. static int FindFileHandler(void)
  273. {
  274.     int i,
  275.     Handler = -1;
  276.  
  277.     for (i = 0; i < MAX_NUM_OF_STREAMS; i++)
  278.     if (!_IPStream[i].InUse) {
  279.         _IPStream[i].InUse = TRUE;
  280.         _IPStream[i].TokenStackPtr = 0;
  281.         _IPStream[i].LineNum = 0;
  282.         _IPStream[i].UnGetChar = -1;
  283.         _IPStream[i].BufferSize = 0;
  284.         _IPStream[i].BufferPtr = 0;
  285.         Handler = i;
  286.         break;
  287.     }
  288.  
  289.     if (i < 0)
  290.     IritPrsrFatalError("Stream table is full.");
  291.  
  292.     return Handler;
  293. }
  294.  
  295. /*****************************************************************************
  296. * DESCRIPTION:                                                               M
  297. * Reads data from a set of files specified by file names.             M
  298. *    Messages and MoreMessages controls the level of printout to stderr.     M
  299. *    Freeform geometry read in is handed out to a call back function named   M
  300. * IritPrsrProcessFreeForm before it is returned from this routine. This      M
  301. * is done so applications that do not want to deal with freeform shapes will M
  302. * be able to provide a call back that processes the freeform shapes into     M
  303. * other geometry such as polygons.                         M
  304. *                                                                            *
  305. * PARAMETERS:                                                                M
  306. *   DataFileNames:    Array of strings (file names) to process.              M
  307. *   NumOfDataFiles:   Number of elements in DataFileNames.                   M
  308. *   Messages:         Do we want error messages?                             M
  309. *   MoreMessages:     Do we want informative messages?                       M
  310. *                                                                            *
  311. * RETURN VALUE:                                                              M
  312. *   IPObjectStruct *:   Objects read from all files.                         M
  313. *                                                                            *
  314. * KEYWORDS:                                                                  M
  315. *   IritPrsrGetDataFiles, files, parser                                      M
  316. *****************************************************************************/
  317. IPObjectStruct *IritPrsrGetDataFiles(char **DataFileNames,
  318.                      int NumOfDataFiles,
  319.                      int Messages,
  320.                      int MoreMessages)
  321. {
  322.     int    i, Handler;
  323.     char *ErrorMsg;
  324.     IPObjectStruct
  325.     *PObjHead = NULL;
  326.  
  327.     for    (i = 0; i < NumOfDataFiles; i++) {
  328.     if (MoreMessages)
  329.         fprintf(stderr, "Reading data file %s\n", *DataFileNames);
  330.  
  331.     if ((Handler = IritPrsrOpenDataFile(*DataFileNames,
  332.                         TRUE, Messages)) < 0)
  333.         continue;
  334.  
  335.     PObjHead = IritPrsrAppendObjLists(IritPrsrGetObjects(Handler),
  336.                       PObjHead);
  337.  
  338.     if (Messages &&
  339.         IritPrsrParseError(_IPStream[Handler].LineNum, &ErrorMsg))
  340.         fprintf(stderr, "File %s, %s\n", *DataFileNames, ErrorMsg);
  341.  
  342.     IritPrsrCloseStream(Handler, TRUE);
  343.  
  344.     DataFileNames++;              /* Skip to next file name. */
  345.     }
  346.  
  347.     if (PObjHead == NULL) {
  348.     if (Messages) {
  349.         char *ErrMsg = "";
  350.  
  351.         if (_IritPrsrGlblParserError != IP_NO_ERR)
  352.         IritPrsrParseError(0, &ErrMsg);
  353.         fprintf(stderr, "No data found. %s\n", ErrMsg);
  354.     }
  355.     return NULL;
  356.     }
  357.  
  358.     return PObjHead;
  359. }
  360.  
  361. /*****************************************************************************
  362. * DESCRIPTION:                                                               M
  363. * Routine to read the data from    a given    file.                     M
  364. *   Returns NULL if EOF was reached or error occured.                 M
  365. *   See also functions IritPrsrSetPolyListCirc, IritPrsrSetFlattenObjects,   M
  366. * and IritPrsrSetReadOneObject.                             M
  367. *                                                                            *
  368. * PARAMETERS:                                                                M
  369. *   Handler:     A handler to the open stream.                     M
  370. *                                                                            *
  371. * RETURN VALUE:                                                              M
  372. *   IPObjectStruct *:   Read object, or NULl if failed.                      M
  373. *                                                                            *
  374. * KEYWORDS:                                                                  M
  375. *   IritPrsrGetObjects, files, parser                                        M
  376. *****************************************************************************/
  377. IPObjectStruct *IritPrsrGetObjects(int Handler)
  378. {
  379.     IPObjectStruct *PObj;
  380.  
  381.     /* If the following gain control and is non zero - its from error! */
  382.     if (setjmp(_IritPrsrLongJumpBuffer) != 0)
  383.     return NULL;
  384.  
  385.     if (_IPStream[Handler].IsBinary) {
  386.     PObj = IritPrsrGetBinObject(Handler);
  387.     }
  388.     else {
  389.     PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
  390.  
  391.     _IritPrsrGlblParserError = IP_NO_ERR;            /* Reset errors. */
  392.  
  393.     IritPrsrGetAllObjects(Handler, PObj, 0);
  394.  
  395.     if (IP_IS_UNDEF_OBJ(PObj)) {
  396.         IPFreeObject(PObj);
  397.         return NULL;
  398.     }
  399.     }
  400.  
  401.     return IritPrsrProcessReadObject(PObj);
  402. }
  403.  
  404. /*****************************************************************************
  405. * DESCRIPTION:                                                               *
  406. * Filters out degenetared list objects with zero or one elements.         *
  407. *                                                                            *
  408. * PARAMETERS:                                                                *
  409. *   PObj:      Read object.                                                  *
  410. *                                                                            *
  411. * RETURN VALUE:                                                              *
  412. *   IPObjectStruct *:   Same object as Pobj but if PObj is a degenerated     *
  413. *                       of one element or even zero element, it is fixed up. *
  414. *****************************************************************************/
  415. static IPObjectStruct *EliminateDegenLists(IPObjectStruct *PObj)
  416. {
  417.     if (PObj == NULL)
  418.     return NULL;
  419.  
  420.     if (IP_IS_OLST_OBJ(PObj)) {
  421.         if (ListObjectGet(PObj, 0) == NULL) {
  422.         /* Nothing read in. */
  423.         IPFreeObject(PObj);
  424.         PObj = NULL;
  425.         _IPParserAbort(IP_ERR_FILE_EMPTY, "");
  426.     }
  427.     else if (ListObjectGet(PObj, 1) == NULL) {
  428.         IPObjectStruct
  429.         *PTmp = ListObjectGet(PObj, 0);
  430.  
  431.         /* Only one object in list - return the object instead. */
  432.         ListObjectInsert(PObj, 0, NULL);
  433.         IPFreeObject(PObj);
  434.         PObj = PTmp;
  435.     }
  436.     }
  437.  
  438.     return PObj;
  439. }
  440.     
  441. /*****************************************************************************
  442. * DESCRIPTION:                                                               M
  443. * Process a read object, in place, before returning it to the caller.         M
  444. *   List objects of zero or one elements are eliminated.                     M
  445. *   Attributes are propagated throughout the hierarchy.                 M
  446. *   If FlattenTree mode (see IritPrsrSetFlattenObjects) hierarchy is         M
  447. * flattened out.                                        M
  448. *                                                                            *
  449. * PARAMETERS:                                                                M
  450. *   PObj:      Object to process.                                            M
  451. *                                                                            *
  452. * RETURN VALUE:                                                              M
  453. *   IPObjectStruct *:   Processed object, in place.                          M
  454. *                                                                            *
  455. * KEYWORDS:                                                                  M
  456. *   IritPrsrProcessReadObject, files, parser                                 M
  457. *****************************************************************************/
  458. IPObjectStruct *IritPrsrProcessReadObject(IPObjectStruct *PObj)
  459. {
  460.     if (PObj == NULL)
  461.     return NULL;
  462.  
  463.     PObj = EliminateDegenLists(PObj);
  464.  
  465.     IritPrsrPropagateAttrs(PObj, NULL);
  466.  
  467.     if (GlblFlattenObjects && PObj != NULL)
  468.     PObj = IritPrsrFlattenTree(PObj);
  469.  
  470.     return PObj;
  471. }
  472.  
  473. /*****************************************************************************
  474. * DESCRIPTION:                                                               M
  475. * Controls vertex list in polygons. Do we want it circular?             M
  476. *                                                                            *
  477. * PARAMETERS:                                                                M
  478. *   Circ:     If TRUE, vertex lists of polygons will be circular. If FALSE,  M
  479. *             the lists will be NULL terminated.                 M
  480. *                                                                            *
  481. * RETURN VALUE:                                                              M
  482. *   void                                                                     M
  483. *                                                                            *
  484. * KEYWORDS:                                                                  M
  485. *   IritPrsrSetPolyListCirc, files, parser                                   M
  486. *****************************************************************************/
  487. void IritPrsrSetPolyListCirc(int Circ)
  488. {
  489.     _IritPrsrPolyListCirc = Circ;
  490. }
  491.  
  492. /*****************************************************************************
  493. * DESCRIPTION:                                                               M
  494. * Controls the hierarchy flattening of a read object.                    M
  495. *                                                                            *
  496. * PARAMETERS:                                                                M
  497. *   Circ:     If TRUE, list objects will be flattened out to a long linear   M
  498. *             list. If FALSE, read object will be unchanged.             M
  499. *                                                                            *
  500. * RETURN VALUE:                                                              M
  501. *   int:      Old value of flatten state.                                    M
  502. *                                                                            *
  503. * KEYWORDS:                                                                  M
  504. *   IritPrsrSetFlattenObjects, files, parser                                 M
  505. *****************************************************************************/
  506. int IritPrsrSetFlattenObjects(int Flatten)
  507. {
  508.     int OldFlatten = GlblFlattenObjects;
  509.  
  510.     GlblFlattenObjects = Flatten;
  511.  
  512.     return OldFlatten;
  513. }
  514.  
  515. /*****************************************************************************
  516. * DESCRIPTION:                                                               M
  517. * Controls the way the Ascii parser handle multiple objects in a file.         M
  518. *                                                                            *
  519. * PARAMETERS:                                                                M
  520. *   Circ:     If TRUE, only next object will be read by IritPrsrGetObjectst. M
  521. *             If FALSE, objects will be read until EOF is detected and       M
  522. *          placed in a linked list.                         M
  523. *                                                                            *
  524. * RETURN VALUE:                                                              M
  525. *   void                                                                     M
  526. *                                                                            *
  527. * KEYWORDS:                                                                  M
  528. *   IritPrsrSetFlattenObjects, files, parser                                 M
  529. *****************************************************************************/
  530. void IritPrsrSetReadOneObject(int OneObject)
  531. {
  532.     _IritPrsrReadOneObject = OneObject;
  533. }
  534.  
  535. /*****************************************************************************
  536. * DESCRIPTION:                                                               M
  537. * Propagate attributes from list objects down into their elements.         M
  538. *                                                                            *
  539. * PARAMETERS:                                                                M
  540. *   PObj:     To propagate down Attrs attributes.                            M
  541. *   Attrs:    Attributes to propagate.                                       M
  542. *                                                                            *
  543. * RETURN VALUE:                                                              M
  544. *   void                                                                     M
  545. *                                                                            *
  546. * KEYWORDS:                                                                  M
  547. *   IritPrsrPropagateAttrs, attributes, files, parser                        M
  548. *****************************************************************************/
  549. void IritPrsrPropagateAttrs(IPObjectStruct *PObj, IPAttributeStruct *Attrs)
  550. {
  551.     IPAttributeStruct *Attr;
  552.  
  553.     if (IP_IS_OLST_OBJ(PObj)) {
  554.     int i;
  555.     IPObjectStruct *PTmp;
  556.  
  557.     /* Collect all attributes of this list (including inherited ones)    */
  558.     /* and propagate them down to the list items.                 */
  559.     if (Attrs != NULL)
  560.         Attrs = AttrCopyAttributes(Attrs);
  561.  
  562.     for (Attr = PObj -> Attrs; Attr != NULL; Attr = Attr -> Pnext) {
  563.         if (!AttrFindAttribute(Attrs, Attr -> Name)) {
  564.         IPAttributeStruct
  565.             *TmpAttr = AttrCopyOneAttribute(Attr);
  566.  
  567.         TmpAttr -> Pnext = Attrs;
  568.         Attrs = TmpAttr;
  569.         }
  570.     }
  571.  
  572.     for (i = 0; (PTmp = ListObjectGet(PObj, i)) != NULL; i++)
  573.         IritPrsrPropagateAttrs(PTmp, Attrs);
  574.  
  575.     AttrFreeAttributes(&Attrs);
  576.     }
  577.     else {
  578.     /* Regular object - add to its attribute list every attribute in     */
  579.     /* Attrs that is not found in its attribute list.             */
  580.     for (Attr = Attrs; Attr != NULL; Attr = Attr -> Pnext) {
  581.         if (!AttrFindAttribute(PObj -> Attrs, Attr -> Name)) {
  582.         IPAttributeStruct
  583.             *TmpAttr = AttrCopyOneAttribute(Attr);
  584.  
  585.         TmpAttr -> Pnext = PObj -> Attrs;
  586.         PObj -> Attrs = TmpAttr;
  587.         }
  588.     }
  589.     }
  590. }
  591.  
  592. /*****************************************************************************
  593. * DESCRIPTION:                                                               M
  594. * Flattens out a tree hierarchy of objects into a linear list, in place.     M
  595. *                                                                            *
  596. * PARAMETERS:                                                                M
  597. *   PObj:      Object(s) to flatten out.                                     M
  598. *                                                                            *
  599. * RETURN VALUE:                                                              M
  600. *   IPObjectStruct *:   Flattened hierarchy.                                 M
  601. *                                                                            *
  602. * KEYWORDS:                                                                  M
  603. *   IritPrsrFlattenTree                                                      M
  604. *****************************************************************************/
  605. IPObjectStruct *IritPrsrFlattenTree(IPObjectStruct *PObj)
  606. {
  607.     IritPrsrFreeFormStruct IPFreeForm;
  608.  
  609.     if (PObj -> Pnext != NULL)
  610.     return PObj;            /* Can only flatten a single hierarchy. */
  611.  
  612.     if (IP_IS_OLST_OBJ(PObj)) {
  613.     int i;
  614.     IPObjectStruct *PTmp, *PTmp2,
  615.         *RetListTail = NULL,
  616.         *RetList = NULL;
  617.  
  618.     for (i = 0; (PTmp = ListObjectGet(PObj, i)) != NULL; i++) {
  619.         /* Zero name of object if it is interior to list. */
  620.         if (strnicmp(PTmp -> Name, "VIEW_MAT", 8) != 0 &&
  621.         strnicmp(PTmp -> Name, "PRSP_MAT", 8) != 0)
  622.         PTmp -> Name[0] = 0;
  623.  
  624.         PTmp2 = IritPrsrFlattenTree(PTmp);
  625.         if (RetList != NULL)
  626.         RetListTail -> Pnext = PTmp2;
  627.         else
  628.         RetList = PTmp2;
  629.         RetListTail = IritPrsrGetLastObj(PTmp2);
  630.     }
  631.  
  632.     ListObjectInsert(PObj, 0, NULL);
  633.     IPFreeObject(PObj);
  634.  
  635.     return RetList;
  636.     }
  637.     else if (IP_IS_CRV_OBJ(PObj)) {
  638.     IPFreeForm.CrvObjs = PObj;
  639.     IPFreeForm.SrfObjs = NULL;
  640.     IPFreeForm.TrimSrfObjs = NULL;
  641.     IPFreeForm.TrivarObjs = NULL;
  642.     return IritPrsrProcessFreeForm(&IPFreeForm);
  643.     }
  644.     else if (IP_IS_SRF_OBJ(PObj)) {
  645.     IPFreeForm.CrvObjs = NULL;
  646.     IPFreeForm.SrfObjs = PObj;
  647.     IPFreeForm.TrimSrfObjs = NULL;
  648.     IPFreeForm.TrivarObjs = NULL;
  649.     return IritPrsrProcessFreeForm(&IPFreeForm);
  650.     }
  651.     else if (IP_IS_TRIMSRF_OBJ(PObj)) {
  652.     IPFreeForm.CrvObjs = NULL;
  653.     IPFreeForm.SrfObjs = NULL;
  654.     IPFreeForm.TrimSrfObjs = PObj;
  655.     IPFreeForm.TrivarObjs = NULL;
  656.     return IritPrsrProcessFreeForm(&IPFreeForm);
  657.     }
  658.     else if (IP_IS_TRIVAR_OBJ(PObj)) {
  659.     IPFreeForm.CrvObjs = NULL;
  660.     IPFreeForm.SrfObjs = NULL;
  661.     IPFreeForm.TrimSrfObjs = NULL;
  662.     IPFreeForm.TrivarObjs = PObj;
  663.     return IritPrsrProcessFreeForm(&IPFreeForm);
  664.     }
  665.     else {
  666.     return PObj;
  667.     }
  668. }
  669.  
  670. /*****************************************************************************
  671. * DESCRIPTION:                                                               *
  672. * Routine to read the geometry data from a given file. Reads "[OBJECT ..."   *
  673. * prefixes only and invoke the auxiliary routine.                 *
  674. *   Objects may be recursively defined.                         *
  675. *                                                                            *
  676. * PARAMETERS:                                                                *
  677. *   Handler:     A handler to the open stream.                     *
  678. *   PObjParent:  One list object, this read object should be hooked as an    *
  679. *                element.                             *
  680. *   Level:       Of recursion.                                               *
  681. *                                                                            *
  682. * RETURN VALUE:                                                              *
  683. *   void                                                                     *
  684. *****************************************************************************/
  685. static void IritPrsrGetAllObjects(int Handler,
  686.                   IPObjectStruct *PObjParent,
  687.                   int Level)
  688. {
  689.     char StringToken[LINE_LEN_LONG];
  690.     IPTokenType Token;
  691.     int    i,
  692.     WasObjectToken = FALSE,
  693.     ObjCount = 0,
  694.     Quit = FALSE;
  695.     IPObjectStruct *PObj;
  696.  
  697.     while (!Quit) {
  698.         while ((Token = _IPGetToken(Handler, StringToken)) !=
  699.                             IP_TOKEN_OPEN_PAREN &&
  700.            Token != IP_TOKEN_CLOSE_PAREN &&
  701.            Token != IP_TOKEN_EOF);
  702.  
  703.     if (Token == IP_TOKEN_CLOSE_PAREN || Token == IP_TOKEN_EOF) {
  704.         if (Token == IP_TOKEN_CLOSE_PAREN)
  705.         _IPUnGetToken(Handler, StringToken);
  706.         Quit = TRUE;
  707.         break;
  708.     }
  709.  
  710.     switch (_IPGetToken(Handler, StringToken)) {
  711.         case IP_TOKEN_OBJECT:
  712.         WasObjectToken = TRUE;
  713.  
  714.             ReallocNewTypeObject(PObjParent, IP_OBJ_LIST_OBJ);
  715.         PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
  716.  
  717.         /* The following handle optional attributes in record. */
  718.         if (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN)
  719.             GetObjectAttributes(PObj, Handler);
  720.         else {
  721.             _IPUnGetToken(Handler, StringToken);
  722.         }
  723.  
  724.         if (AttrGetObjectColor(PObj) == IP_ATTR_NO_COLOR)
  725.             AttrSetObjectColor(PObj, IP_LOAD_COLOR);
  726.  
  727.         if (_IPGetToken(Handler, StringToken) == IP_TOKEN_OTHER &&
  728.             stricmp(StringToken, "NONE") != 0) {
  729.             for (i = 0; i < strlen(StringToken); i++)
  730.                 PObj -> Name[i] =
  731.                 islower(StringToken[i]) ? toupper(StringToken[i])
  732.                             : StringToken[i];
  733.             PObj -> Name[i] = 0;
  734.         }
  735.  
  736.         IritPrsrGetAllObjects(Handler, PObj, Level + 1);
  737.  
  738.         _IPGetCloseParenToken(Handler);
  739.  
  740.         if (IP_IS_UNDEF_OBJ(PObj))
  741.             _IPParserAbort(IP_ERR_OBJECT_EMPTY, "");
  742.  
  743.         ListObjectInsert(PObjParent, ObjCount++, PObj);
  744.         break;
  745.         default:
  746.         if (WasObjectToken) {
  747.             _IPParserAbort(IP_ERR_OBJECT_EXPECTED, StringToken);
  748.         }
  749.         _IPUnGetToken(Handler, StringToken);
  750.         _IPUnGetToken(Handler, "[");
  751.         IritPrsrGetAuxObject(Handler, PObjParent);
  752.         Quit = TRUE;
  753.         break;
  754.     }
  755.  
  756.     if (Level == 0 && WasObjectToken && _IritPrsrReadOneObject)
  757.         Quit = TRUE;
  758.     }
  759.  
  760.     if (IP_IS_OLST_OBJ(PObjParent)) {
  761.     ListObjectInsert(PObjParent, ObjCount++, NULL);
  762.     }
  763. }
  764.  
  765. /*****************************************************************************
  766. * DESCRIPTION:                                                               M
  767. * Routine to get close paren token from FILE f.                     M
  768. *   This function invokes the parser's abort routine, if no close paren.     M
  769. *                                                                            *
  770. * PARAMETERS:                                                                M
  771. *   Handler:     A handler to the open stream.                     M
  772. *                                                                            *
  773. * RETURN VALUE:                                                              M
  774. *   void                                                                     M
  775. *                                                                            *
  776. * KEYWORDS:                                                                  M
  777. *   _IPGetCloseParenToken                             M
  778. *****************************************************************************/
  779. void _IPGetCloseParenToken(int Handler)
  780. {
  781.     char StringToken[LINE_LEN_LONG];
  782.  
  783.     if (_IPGetToken(Handler, StringToken) != IP_TOKEN_CLOSE_PAREN)
  784.     _IPParserAbort(IP_ERR_CLOSE_PAREN_EXPECTED, StringToken);
  785. }
  786.  
  787. /*****************************************************************************
  788. * DESCRIPTION:                                                               M
  789. * Routine to skip to the next closed parenthesis.                            M
  790. *                                                                            *
  791. * PARAMETERS:                                                                M
  792. *   Handler:     A handler to the open stream.                     M
  793. *                                                                            *
  794. * RETURN VALUE:                                                              M
  795. *   int:    TRUE, if found close paren.                                  M
  796. *                                                                            *
  797. * KEYWORDS:                                                                  M
  798. *   _IPSkipToCloseParenToken                             M
  799. *****************************************************************************/
  800. int _IPSkipToCloseParenToken(int Handler)
  801. {
  802.     char StringToken[LINE_LEN_LONG];
  803.     IPTokenType
  804.     Token = IP_TOKEN_EOF;
  805.  
  806.     while (!InputEOF(Handler) &&
  807.       (Token = _IPGetToken(Handler, StringToken)) != IP_TOKEN_CLOSE_PAREN);
  808.  
  809.     return Token == IP_TOKEN_CLOSE_PAREN;
  810. }
  811.  
  812. /*****************************************************************************
  813. * DESCRIPTION:                                                               *
  814. * Routine to get one numeric token into r.                     *
  815. *                                                                            *
  816. * PARAMETERS:                                                                *
  817. *   Handler:     A handler to the open stream.                     *
  818. *   r:           Where numeric data should go to.                            *
  819. *                                                                            *
  820. * RETURN VALUE:                                                              *
  821. *   void                                                                     *
  822. *****************************************************************************/
  823. static void GetNumericToken(int Handler, RealType *r)
  824. {
  825.     char StringToken[LINE_LEN_LONG];
  826.  
  827.     _IPGetToken(Handler, StringToken);
  828.     if (sscanf(StringToken, IP_FLOAT_READ, r) != 1)
  829.         _IPParserAbort(IP_ERR_NUMBER_EXPECTED, StringToken);
  830. }
  831.  
  832. /*****************************************************************************
  833. * DESCRIPTION:                                                               *
  834. * Routine to read the content of a single object.                            *
  835. *                                                                            *
  836. * PARAMETERS:                                                                *
  837. *   Handler:     A handler to the open stream.                     *
  838. *   PObj:        Where to place the read object.                             *
  839. *                                                                            *
  840. * RETURN VALUE:                                                              *
  841. *   void                                                                     *
  842. *****************************************************************************/
  843. static void IritPrsrGetAuxObject(int Handler, IPObjectStruct *PObj)
  844. {
  845.     int    i, j, ErrLine;
  846.     IPTokenType
  847.     Token = IP_TOKEN_NONE;
  848.     char *ErrStr, StringToken[LINE_LEN_LONG];
  849.     CagdRType *Coords;
  850.     IPPolygonStruct *PPolygon;
  851.     CagdCrvStruct *PCurve;
  852.     CagdSrfStruct *PSurface;
  853.     TrimSrfStruct *PTrimSrf;
  854.     TrivTVStruct *PTrivar;
  855.  
  856.     ReallocNewTypeObject(PObj, IP_OBJ_UNDEF);
  857.  
  858.     while (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN) {
  859.     switch (Token = _IPGetToken(Handler, StringToken)) {
  860.         case IP_TOKEN_POLYGON:
  861.         case IP_TOKEN_POLYLINE:
  862.         case IP_TOKEN_POINTLIST:
  863.         ReallocNewTypeObject(PObj, IP_OBJ_POLY);
  864.         PPolygon = IPAllocPolygon(0, 0, NULL, NULL);
  865.         switch (Token) {
  866.             case IP_TOKEN_POLYGON:
  867.             IP_SET_POLYGON_OBJ(PObj);
  868.             break;
  869.             case IP_TOKEN_POLYLINE:
  870.             IP_SET_POLYLINE_OBJ(PObj);
  871.             break;
  872.             case IP_TOKEN_POINTLIST:
  873.             IP_SET_POINTLIST_OBJ(PObj);
  874.             break;
  875.             default:
  876.             _IPParserAbort(IP_ERR_UNDEF_EXPR_HEADER,
  877.                         StringToken);
  878.             break;
  879.         }
  880.  
  881.         /* The following handle the optional attributes in struct.   */
  882.         if (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN)
  883.             GetPolygonAttributes(PPolygon, Handler);
  884.         else
  885.             _IPUnGetToken(Handler, StringToken);
  886.  
  887.         /* The following handles reading the vertices. */
  888.         GetPointData(Handler, PPolygon, IP_IS_POLYGON_OBJ(PObj));
  889.  
  890.         if (IP_IS_POLYGON_OBJ(PObj)) {
  891.             if (!IP_HAS_PLANE_POLY(PPolygon))
  892.             IritPrsrUpdatePolyPlane(PPolygon);
  893.  
  894.             IritPrsrUpdateVrtxNrml(PPolygon, PPolygon -> Plane);
  895.         }
  896.  
  897.         PPolygon -> Pnext = PObj -> U.Pl;
  898.         PObj -> U.Pl = PPolygon;
  899.         break;
  900.         case IP_TOKEN_SURFACE:
  901.         ReallocNewTypeObject(PObj, IP_OBJ_SURFACE);
  902.         ErrLine = _IPStream[Handler].LineNum;
  903.         PSurface = CagdSrfReadFromFile2(Handler, &ErrStr, &ErrLine);
  904.         _IPStream[Handler].LineNum = ErrLine;
  905.  
  906.         if (ErrStr != NULL) {
  907.             _IPParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr);
  908.             break;
  909.         }
  910.  
  911.         if (PSurface != NULL) {
  912.             PSurface -> Pnext = PObj -> U.Srfs;
  913.             PObj -> U.Srfs = PSurface;
  914.         }
  915.         break;
  916.         case IP_TOKEN_CURVE:
  917.         ReallocNewTypeObject(PObj, IP_OBJ_CURVE);
  918.         ErrLine = _IPStream[Handler].LineNum;
  919.         PCurve = CagdCrvReadFromFile2(Handler, &ErrStr, &ErrLine);
  920.         _IPStream[Handler].LineNum = ErrLine;
  921.  
  922.         if (ErrStr != NULL) {
  923.             _IPParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr);
  924.             break;
  925.         }
  926.  
  927.         if (PCurve != NULL) {
  928.             PCurve -> Pnext = PObj -> U.Crvs;
  929.             PObj -> U.Crvs = PCurve;
  930.         }
  931.         break;
  932.         case IP_TOKEN_TRIMSRF:
  933.         ReallocNewTypeObject(PObj, IP_OBJ_TRIMSRF);
  934.         ErrLine = _IPStream[Handler].LineNum;
  935.         PTrimSrf = TrimReadTrimmedSrfFromFile2(Handler, TRUE,
  936.                                &ErrStr, &ErrLine);
  937.         _IPStream[Handler].LineNum = ErrLine;
  938.  
  939.         if (ErrStr != NULL) {
  940.             _IPParserAbort(IP_ERR_TRIM_LIB_ERR, ErrStr);
  941.             break;
  942.         }
  943.  
  944.         if (PTrimSrf != NULL) {
  945.             PTrimSrf -> Pnext = PObj -> U.TrimSrfs;
  946.             PObj -> U.TrimSrfs = PTrimSrf;
  947.         }
  948.         break;
  949.         case IP_TOKEN_TRIVAR:
  950.         ReallocNewTypeObject(PObj, IP_OBJ_TRIVAR);
  951.         ErrLine = _IPStream[Handler].LineNum;
  952.         PTrivar = TrivTVReadFromFile2(Handler, &ErrStr, &ErrLine);
  953.         _IPStream[Handler].LineNum = ErrLine;
  954.  
  955.         if (ErrStr != NULL) {
  956.             _IPParserAbort(IP_ERR_TRIV_LIB_ERR, ErrStr);
  957.             break;
  958.         }
  959.  
  960.         if (PTrivar != NULL) {
  961.             PTrivar -> Pnext = PObj -> U.Trivars;
  962.             PObj -> U.Trivars = PTrivar;
  963.         }
  964.         break;
  965.         case IP_TOKEN_NUMBER:
  966.         ReallocNewTypeObject(PObj, IP_OBJ_NUMERIC);
  967.         GetNumericToken(Handler, &PObj -> U.R);
  968.         _IPGetCloseParenToken(Handler);
  969.         break;
  970.         case IP_TOKEN_STRING:
  971.         ReallocNewTypeObject(PObj, IP_OBJ_STRING);
  972.         _IPGetToken(Handler, PObj -> U.Str);
  973.         _IPGetCloseParenToken(Handler);
  974.         break;
  975.         case IP_TOKEN_POINT:
  976.         ReallocNewTypeObject(PObj, IP_OBJ_POINT);
  977.         for (i = 0; i < 3; i++)
  978.             GetNumericToken(Handler, &PObj -> U.Pt[i]);
  979.         _IPGetCloseParenToken(Handler);
  980.         break;
  981.         case IP_TOKEN_VECTOR:
  982.         ReallocNewTypeObject(PObj, IP_OBJ_VECTOR);
  983.         for (i = 0; i < 3; i++)
  984.             GetNumericToken(Handler, &PObj -> U.Vec[i]);
  985.         _IPGetCloseParenToken(Handler);
  986.         break;
  987.         case IP_TOKEN_PLANE:
  988.         ReallocNewTypeObject(PObj, IP_OBJ_PLANE);
  989.         for (i = 0; i < 4; i++)
  990.             GetNumericToken(Handler, &PObj -> U.Plane[i]);
  991.         _IPGetCloseParenToken(Handler);
  992.         break;
  993.         case IP_TOKEN_MATRIX:
  994.         ReallocNewTypeObject(PObj, IP_OBJ_MATRIX);
  995.         for (i = 0; i < 4; i++)
  996.             for (j = 0; j < 4; j++)
  997.             GetNumericToken(Handler, &(*PObj -> U.Mat)[i][j]);
  998.         _IPGetCloseParenToken(Handler);
  999.  
  1000.         if (stricmp(PObj -> Name, "VIEW_MAT") == 0) {
  1001.             IritPrsrWasViewMat = TRUE;
  1002.             MAT_COPY(IritPrsrViewMat, PObj -> U.Mat);
  1003.         }
  1004.         else if (stricmp(PObj -> Name, "PRSP_MAT") == 0) {
  1005.             IritPrsrWasPrspMat = TRUE;
  1006.             MAT_COPY(IritPrsrPrspMat, PObj -> U.Mat);
  1007.         }
  1008.         break;
  1009.         case IP_TOKEN_CTLPT:
  1010.         ReallocNewTypeObject(PObj, IP_OBJ_CTLPT);
  1011.         _IPGetToken(Handler, StringToken);
  1012.  
  1013.         i = atoi(&StringToken[1]);
  1014.         if ((StringToken[0] == 'P' || StringToken[0] == 'E' ) &&
  1015.             i > 0 && i < 6) {
  1016.            j = StringToken[0] == 'E';
  1017.            PObj -> U.CtlPt.PtType = CAGD_MAKE_PT_TYPE(!j, i);
  1018.         }
  1019.         else {
  1020.             _IPParserAbort(IP_ERR_PT_TYPE_EXPECTED, StringToken);
  1021.             i = j = 0;
  1022.             break;
  1023.         }
  1024.  
  1025.         Coords = PObj -> U.CtlPt.Coords;
  1026.         for ( i += 1 - j; i > 0; i--)
  1027.             GetNumericToken(Handler, &Coords[j++]);
  1028.         _IPGetCloseParenToken(Handler);
  1029.         break;
  1030.         default:
  1031.         _IPParserAbort(IP_ERR_UNDEF_EXPR_HEADER, StringToken);
  1032.         break;
  1033.     } /* Of switch. */
  1034.     } /* Of while. */
  1035.  
  1036.     _IPUnGetToken(Handler, StringToken);
  1037. }
  1038.  
  1039. /*****************************************************************************
  1040. * DESCRIPTION:                                                               M
  1041. *   Routine to unget one token (on stack of UNGET_STACK_SIZE levels!)         M
  1042. *                                                                            *
  1043. * PARAMETERS:                                                                M
  1044. *   Handler:       A handler to the open stream.                 M
  1045. *   StringToken:   Token to unget                                            M
  1046. *                                                                            *
  1047. * RETURN VALUE:                                                              M
  1048. *   void                                                                     M
  1049. *                                                                            *
  1050. * KEYWORDS:                                                                  M
  1051. *   _IPUnGetToken                                 M
  1052. *****************************************************************************/
  1053. void _IPUnGetToken(int Handler, char *StringToken)
  1054. {
  1055.     if (_IPStream[Handler].TokenStackPtr >= UNGET_STACK_SIZE)
  1056.      _IPParserAbort(IP_ERR_STACK_OVERFLOW, "");
  1057.  
  1058.     strcpy(_IPStream[Handler].TokenStack[_IPStream[Handler].TokenStackPtr++],
  1059.        StringToken);
  1060. }
  1061.  
  1062. /*****************************************************************************
  1063. * DESCRIPTION:                                                               M
  1064. * Routine to unget a single character from input stream.             M
  1065. *                                                                            *
  1066. * PARAMETERS:                                                                M
  1067. *   Handler:   A handler to the open stream.                     M
  1068. *   c:         Character to unget.                                           M
  1069. *                                                                            *
  1070. * RETURN VALUE:                                                              M
  1071. *   void                                                                     M
  1072. *                                                                            *
  1073. * KEYWORDS:                                                                  M
  1074. *   IritPrsrInputUnGetC, files, parser                                       M
  1075. *****************************************************************************/
  1076. void IritPrsrInputUnGetC(int Handler, char c)
  1077. {
  1078.     _IPStream[Handler].UnGetChar = c;
  1079. }
  1080.  
  1081. /*****************************************************************************
  1082. * DESCRIPTION:                                                               *
  1083. * Routine to get a single character from input stream.                 *
  1084. *   If input returns EOF block until new input arrives (can happen if        *
  1085. * reading from a non io blocked socket).                     *
  1086. *                                                                            *
  1087. * PARAMETERS:                                                                *
  1088. *   Handler:   A handler to the open stream.                     *
  1089. *                                                                            *
  1090. * RETURN VALUE:                                                              *
  1091. *   int:       Read character.                                               *
  1092. *****************************************************************************/
  1093. static int InputGetC(int Handler)
  1094. {
  1095.     int c;
  1096.  
  1097.     if (_IPStream[Handler].UnGetChar >= 0) {
  1098.     c = _IPStream[Handler].UnGetChar;
  1099.  
  1100.     _IPStream[Handler].UnGetChar = -1;
  1101.     }
  1102.     else if (_IPStream[Handler].f != NULL) {
  1103.     c = getc(_IPStream[Handler].f);
  1104.     }
  1105.     else {
  1106.     while ((c = SocReadCharNonBlock(Handler)) == EOF)
  1107.         IritSleep(10);
  1108.     }
  1109.  
  1110.     if (c < ' ' && c > 0 && c != '\n' && c != '\r' && c != '\t')
  1111.         _IPParserAbort(IP_ERR_BIN_IN_TEXT, "Is it a binary file!?");
  1112.  
  1113.     return c;
  1114. }
  1115.  
  1116. /*****************************************************************************
  1117. * DESCRIPTION:                                                               *
  1118. * Routine to test for EOF condition in input stream.                 *
  1119. *                                                                            *
  1120. * PARAMETERS:                                                                *
  1121. *   Handler:   A handler to the open stream.                     *
  1122. *                                                                            *
  1123. * RETURN VALUE:                                                              *
  1124. *   int:      TRUE if EOF detected.                                          *
  1125. *****************************************************************************/
  1126. static int InputEOF(int Handler)
  1127. {
  1128.     if (_IPStream[Handler].f != NULL)
  1129.     return feof(_IPStream[Handler].f);
  1130.     else
  1131.     return FALSE;
  1132. }
  1133.  
  1134. /*****************************************************************************
  1135. * DESCRIPTION:                                                               *
  1136. * Routine to get the next token out of the input file f.             *
  1137. *   Returns TRUE if !InputEOF and the next token found in StringToken.         *
  1138. *   StringToken must be allocated before calling this routine!             *
  1139. *                                                                            *
  1140. * PARAMETERS:                                                                *
  1141. *   Handler:      A handler to the open stream.                     *
  1142. *   StringToken:  String token will be placed herein.                        *
  1143. *   Quoted:       If we detected a quoated string: "xxx yyy".                *
  1144. *                                                                            *
  1145. * RETURN VALUE:                                                              *
  1146. *   int:          TRUE if successful.                                        *
  1147. *****************************************************************************/
  1148. static int GetStringToken(int Handler, char *StringToken, int *Quoted)
  1149. {
  1150.     int    len;
  1151.     char *LocalStringToken,
  1152.     c = EOF;
  1153.  
  1154.     *Quoted = FALSE;
  1155.  
  1156.     if (_IPStream[Handler].TokenStackPtr) { /*    get first the unget token */
  1157.     strcpy(StringToken, _IPStream[Handler].TokenStack[--_IPStream[Handler].
  1158.                                    TokenStackPtr]);
  1159.     return TRUE;
  1160.     }
  1161.     /* skip white spaces: */
  1162.     while ((!InputEOF(Handler)) &&
  1163.        (((c = InputGetC(Handler)) == ' ') || (c == '\t') || (c == '\n')) &&
  1164.        (c != (char) EOF))
  1165.     if (c == '\n')
  1166.         _IPStream[Handler].LineNum++;         /* Count the lines. */
  1167.  
  1168.     LocalStringToken = StringToken;
  1169.     if (c == '[')              /* Its a token by    itself so return it. */
  1170.     *LocalStringToken++ = c;          /* Copy the token    into string. */
  1171.     else {
  1172.     if (!InputEOF(Handler) && (c != (char) EOF)) {
  1173.         if (c == '"') {
  1174.         *Quoted = TRUE;
  1175.         while ((!InputEOF(Handler)) &&
  1176.                ((c = InputGetC(Handler)) != '"') &&
  1177.                (c != '\n') &&
  1178.                (c != (char) EOF)) {
  1179.             *LocalStringToken++ = c;      /* Copy the quoted string. */
  1180.             if (c == '\\') {
  1181.             /* Next character is quoted - copy verbatim. */
  1182.             *--LocalStringToken = c = InputGetC(Handler);
  1183.             LocalStringToken++;
  1184.             }
  1185.         }
  1186.         }
  1187.         else {
  1188.         do
  1189.             *LocalStringToken++ = c;  /* Copy the token into string. */
  1190.         while ((!InputEOF(Handler)) &&
  1191.                ((c = InputGetC(Handler)) != ' ') &&
  1192.                (c != '\t') &&
  1193.                (c != '\n') &&
  1194.                (c != (char) EOF));
  1195.         }
  1196.         if (!InputEOF(Handler) && c == '\n')
  1197.             IritPrsrInputUnGetC(Handler, c);      /* Save for next time. */
  1198.     }
  1199.     }
  1200.     *LocalStringToken =    0;                     /* Put    eos. */
  1201.  
  1202.     /* The following handles the spacial case were we have XXXX] - we must   */
  1203.     /* split it    into two token XXXX and    ], _IPUnGetToken(']') & return XXXX: */
  1204.     if (!*Quoted &&
  1205.     (StringToken[len = strlen(StringToken) - 1] == ']') &&
  1206.     (len > 0)) {
  1207.     /* Return CloseParan */
  1208.     _IPUnGetToken(Handler, &StringToken[len]);     /* Save next token. */
  1209.     StringToken[len] = 0;            /* Set end of string on    "]". */
  1210.     }
  1211.  
  1212.     return !InputEOF(Handler) && (c != (char) EOF);
  1213. }
  1214.  
  1215. /*****************************************************************************
  1216. * DESCRIPTION:                                                               M
  1217. * Routine to get the next token out of the input file f as token number.     M
  1218. *   StringToken must be allocated before calling this routine!             M
  1219. *                                                                            *
  1220. * PARAMETERS:                                                                M
  1221. *   Handler:       A handler to the open stream.                 M
  1222. *   StringToken:   String token will be placed herein.                       M
  1223. *                                                                            *
  1224. * RETURN VALUE:                                                              M
  1225. *   IPTokenType:   Token as a numeral.                                       M
  1226. *                                                                            *
  1227. * KEYWORDS:                                                                  M
  1228. *   _IPGetToken                                            M
  1229. *****************************************************************************/
  1230. IPTokenType _IPGetToken(int Handler, char *StringToken)
  1231. {
  1232.     static int IntTokens[] = {
  1233.     IP_TOKEN_OPEN_PAREN,
  1234.     IP_TOKEN_CLOSE_PAREN,
  1235.     IP_TOKEN_E1,
  1236.     IP_TOKEN_P1,
  1237.     IP_TOKEN_E2,
  1238.     IP_TOKEN_P2,
  1239.     IP_TOKEN_E3,
  1240.     IP_TOKEN_P3,
  1241.     IP_TOKEN_E4,
  1242.     IP_TOKEN_P4,
  1243.     IP_TOKEN_E5,
  1244.     IP_TOKEN_P5,
  1245.     IP_TOKEN_NUMBER,
  1246.     IP_TOKEN_STRING,
  1247.     IP_TOKEN_POINT,
  1248.     IP_TOKEN_VECTOR,
  1249.     IP_TOKEN_MATRIX,
  1250.     IP_TOKEN_CTLPT,
  1251.     IP_TOKEN_VERTEX,
  1252.     IP_TOKEN_POLYGON,
  1253.     IP_TOKEN_POLYLINE,
  1254.     IP_TOKEN_POINTLIST,
  1255.     IP_TOKEN_OBJECT,
  1256.     IP_TOKEN_COLOR,
  1257.     IP_TOKEN_RGB,
  1258.     IP_TOKEN_INTERNAL,
  1259.     IP_TOKEN_NORMAL,
  1260.     IP_TOKEN_PLANE,
  1261.     IP_TOKEN_CURVE,
  1262.     IP_TOKEN_SURFACE,
  1263.     IP_TOKEN_BEZIER,
  1264.     IP_TOKEN_BSPLINE,
  1265.     IP_TOKEN_POWER,
  1266.     IP_TOKEN_TRIVAR,
  1267.     IP_TOKEN_PTYPE,
  1268.     IP_TOKEN_NUM_PTS,
  1269.     IP_TOKEN_ORDER,
  1270.     IP_TOKEN_KV,
  1271.     IP_TOKEN_KVP,
  1272.     IP_TOKEN_TRIMMDL,
  1273.     IP_TOKEN_TRIMSRF,
  1274.     IP_TOKEN_TRIMCRV,
  1275.     IP_TOKEN_TRIMCRVSEG,
  1276.  
  1277.     0
  1278.     };
  1279.     static char *StrTokens[] = {
  1280.     "[",
  1281.     "]",
  1282.     "E1",
  1283.     "P1",
  1284.     "E2",
  1285.     "P2",
  1286.     "E3",
  1287.     "P3",
  1288.     "E4",
  1289.     "P4",
  1290.     "E5",
  1291.     "P5",
  1292.     "NUMBER",
  1293.     "STRING",
  1294.     "POINT",
  1295.     "VECTOR",
  1296.     "MATRIX",
  1297.     "CTLPT",
  1298.     "VERTEX",
  1299.     "POLYGON",
  1300.     "POLYLINE",
  1301.     "POINTLIST",
  1302.     "OBJECT",
  1303.     "COLOR",
  1304.     "RGB",
  1305.     "INTERNAL",
  1306.     "NORMAL",
  1307.     "PLANE",
  1308.     "CURVE",
  1309.     "SURFACE",
  1310.     "BEZIER",
  1311.     "BSPLINE",
  1312.     "POWER",
  1313.     "TRIVAR",
  1314.     "PTYPE",
  1315.     "NUMPTS",
  1316.     "ORDER",
  1317.     "KV",
  1318.     "KVP",
  1319.     "TRIMMODEL",
  1320.     "TRIMSRF",
  1321.     "TRIMCRV",
  1322.     "TRIMCRVSEG",
  1323.  
  1324.     NULL
  1325.     };
  1326.     int i, Quoted;
  1327.  
  1328.     if (!GetStringToken(Handler, StringToken, &Quoted))
  1329.     return IP_TOKEN_EOF;
  1330.  
  1331.     if (Quoted)
  1332.     return IP_TOKEN_QUOTED;
  1333.  
  1334.     for (i = 0; StrTokens[i] != NULL; i++)
  1335.     if (stricmp(StringToken, StrTokens[i]) == 0)
  1336.         return IntTokens[i];
  1337.  
  1338.     return IP_TOKEN_OTHER;              /* Must be number or name. */
  1339. }
  1340.  
  1341. /*****************************************************************************
  1342. * DESCRIPTION:                                                               *
  1343. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  1344. *   The first '[' was already read.                         *
  1345. *                                                                            *
  1346. * PARAMETERS:                                                                *
  1347. *   PVertex:    Where attributes should go to.                               *
  1348. *   Handler:    A handler to the open stream.                     *
  1349. *                                                                            *
  1350. * RETURN VALUE:                                                              *
  1351. *   void                                                                     *
  1352. *****************************************************************************/
  1353. static void GetVertexAttributes(IPVertexStruct *PVertex, int Handler)
  1354. {
  1355.     int i;
  1356.     RealType Len;
  1357.     char StringToken[LINE_LEN_LONG];
  1358.  
  1359.     do {
  1360.     switch (_IPGetToken(Handler, StringToken)) {
  1361.         case IP_TOKEN_INTERNAL:
  1362.         _IPGetCloseParenToken(Handler);
  1363.         IP_SET_INTERNAL_VRTX(PVertex);
  1364.         break;
  1365.         case IP_TOKEN_NORMAL:
  1366.         /* The following handles reading 3 coord. of vertex normal. */
  1367.         for (i = 0; i < 3; i++)
  1368.             GetNumericToken(Handler, &PVertex -> Normal[i]);
  1369.  
  1370.         /* Make sure it is normalized. */
  1371.         Len = PT_LENGTH(PVertex -> Normal);
  1372.         if (Len > 0) {
  1373.             for (i = 0; i < 3; i++)
  1374.             PVertex -> Normal[i] /= Len;
  1375.             IP_SET_NORMAL_VRTX(PVertex);
  1376.         }
  1377.         _IPGetCloseParenToken(Handler);
  1378.         break;
  1379.         default:
  1380.         GetGenericAttribute(&PVertex -> Attrs, Handler, StringToken);
  1381.         break;
  1382.     }
  1383.     }
  1384.     while (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN);
  1385.  
  1386.     _IPUnGetToken(Handler, StringToken);
  1387. }
  1388.  
  1389. /*****************************************************************************
  1390. * DESCRIPTION:                                                               *
  1391. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  1392. *   The first '[' was already read.                         *
  1393. *                                                                            *
  1394. * PARAMETERS:                                                                *
  1395. *   PPolygon:   Where attributes should go to.                               *
  1396. *   Handler:    A handler to the open stream.                     *
  1397. *                                                                            *
  1398. * RETURN VALUE:                                                              *
  1399. *   void                                                                     *
  1400. *****************************************************************************/
  1401. static void GetPolygonAttributes(IPPolygonStruct *PPolygon, int Handler)
  1402. {
  1403.     int i;
  1404.     RealType Len;
  1405.     char StringToken[LINE_LEN_LONG];
  1406.  
  1407.     do {
  1408.     switch (_IPGetToken(Handler, StringToken)) {
  1409.         case IP_TOKEN_PLANE:
  1410.         /* The following handles reading of 4 coord. of plane eqn.. */
  1411.         for (i = 0; i < 4; i++)
  1412.             GetNumericToken(Handler, &PPolygon -> Plane[i]);
  1413.  
  1414.         /* Make sure it is normalized. */
  1415.         Len = PT_LENGTH(PPolygon -> Plane);
  1416.         if (Len > 0)
  1417.             for (i = 0; i < 4; i++)
  1418.             PPolygon -> Plane[i] /= Len;
  1419.         else
  1420.             _IPParserAbort(IP_ERR_DEGEN_NORMAL, "");
  1421.  
  1422.         _IPGetCloseParenToken(Handler);
  1423.         IP_SET_PLANE_POLY(PPolygon);
  1424.         break;
  1425.         default:
  1426.         GetGenericAttribute(&PPolygon -> Attrs, Handler, StringToken);
  1427.         break;
  1428.     }
  1429.     }
  1430.     while (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN);
  1431.  
  1432.     _IPUnGetToken(Handler, StringToken);
  1433. }
  1434.  
  1435. /*****************************************************************************
  1436. * DESCRIPTION:                                                               *
  1437. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  1438. *   The first '[' was already read.                         *
  1439. *                                                                            *
  1440. * PARAMETERS:                                                                *
  1441. *   PObject:    Where attributes should go to.                               *
  1442. *   Handler:    A handler to the open stream.                     *
  1443. *                                                                            *
  1444. * RETURN VALUE:                                                              *
  1445. *   void                                                                     *
  1446. *****************************************************************************/
  1447. static void GetObjectAttributes(IPObjectStruct *PObject, int Handler)
  1448. {
  1449.     int    i;
  1450.     char StringToken[LINE_LEN_LONG];
  1451.  
  1452.     do {
  1453.     switch (_IPGetToken(Handler, StringToken)) {
  1454.         case IP_TOKEN_COLOR:
  1455.         _IPGetToken(Handler, StringToken);
  1456.         if (sscanf(StringToken, "%d", &i) != 1)
  1457.             _IPParserAbort(IP_ERR_NUMBER_EXPECTED, StringToken);
  1458.         _IPGetCloseParenToken(Handler);
  1459.         AttrSetObjectColor(PObject, i);
  1460.         break;
  1461.         default:
  1462.         GetGenericAttribute(&PObject -> Attrs, Handler, StringToken);
  1463.         break;
  1464.     }
  1465.     }
  1466.     while (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN);
  1467.  
  1468.     if (AttrGetObjectColor(PObject) == IP_ATTR_NO_COLOR)
  1469.         AttrSetObjectColor(PObject, IP_LOAD_COLOR);
  1470.  
  1471.     _IPUnGetToken(Handler, StringToken);
  1472. }
  1473.  
  1474. /*****************************************************************************
  1475. * DESCRIPTION:                                                               *
  1476. * Routine to read one generic attribute.                     *
  1477. *                                                                            *
  1478. * PARAMETERS:                                                                *
  1479. *   Attrs:    Where to place the read attribute.                             *
  1480. *   Handler:  A handler to the open stream.                     *
  1481. *   Name:     Name of attribute.                                             *
  1482. *                                                                            *
  1483. * RETURN VALUE:                                                              *
  1484. *   void                                                                     *
  1485. *****************************************************************************/
  1486. static void GetGenericAttribute(IPAttributeStruct **Attrs,
  1487.                 int Handler,
  1488.                 char *Name)
  1489. {
  1490.     int Token;
  1491.     char StringToken[LINE_LEN_LONG];
  1492.  
  1493.     if ((Token = _IPGetToken(Handler, StringToken)) == IP_TOKEN_CLOSE_PAREN) {
  1494.     AttrSetStrAttrib(Attrs, Name, "");
  1495.     }
  1496.     else if (Token == IP_TOKEN_QUOTED) {
  1497.     AttrSetStrAttrib(Attrs, Name, StringToken);
  1498.  
  1499.     _IPSkipToCloseParenToken(Handler);
  1500.     }
  1501.     else if (Token == IP_TOKEN_OPEN_PAREN) {
  1502.     IPObjectStruct
  1503.         *PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
  1504.  
  1505.     _IPUnGetToken(Handler, StringToken);
  1506.     IritPrsrGetAllObjects(Handler, PObj, 10);
  1507.     PObj = EliminateDegenLists(PObj);
  1508.  
  1509.     AttrSetObjAttrib(Attrs, Name, PObj, FALSE);
  1510.  
  1511.     _IPSkipToCloseParenToken(Handler);
  1512.     }
  1513.     else {
  1514.     int i;
  1515.     RealType d;
  1516.  
  1517.     for (i = strlen(StringToken) - 1; i >= 0; i--) {
  1518.         if (!(isdigit(StringToken[i]) ||
  1519.           StringToken[i] == 'e' ||
  1520.           StringToken[i] == 'E' ||
  1521.           StringToken[i] == '.' ||
  1522.           StringToken[i] == '+' ||
  1523.           StringToken[i] == '-'))
  1524.         break;
  1525.     }
  1526.     if (i < 0 && sscanf(StringToken, IP_FLOAT_READ, &d) == 1) {
  1527.         if (d == (int) d)
  1528.         AttrSetIntAttrib(Attrs, Name, (int) d);
  1529.         else
  1530.         AttrSetRealAttrib(Attrs, Name, d);
  1531.     }
  1532.     else
  1533.         AttrSetStrAttrib(Attrs, Name, StringToken);
  1534.  
  1535.     _IPSkipToCloseParenToken(Handler);
  1536.     }
  1537. }
  1538.  
  1539. /*****************************************************************************
  1540. * DESCRIPTION:                                                               *
  1541. * Routine to read poly vertex information.                     *
  1542. *                                                                            *
  1543. * PARAMETERS:                                                                *
  1544. *   Handler:     A handler to the open stream.                     *
  1545. *   PPolygon:    Where vertices are to be placed.                            *
  1546. *   IsPolygon:   Should we expect a polygon or a polyline? a pointlist?      *
  1547. *                                                                            *
  1548. * RETURN VALUE:                                                              *
  1549. *   void                                                                     *
  1550. *****************************************************************************/
  1551. static void GetPointData(int Handler, IPPolygonStruct *PPolygon, int IsPolygon)
  1552. {
  1553.     int i, j, Length;
  1554.     char StringToken[LINE_LEN_LONG];
  1555.     IPVertexStruct *V,
  1556.     *VTail = NULL;
  1557.  
  1558.     if (_IPGetToken(Handler, StringToken) != IP_TOKEN_OTHER ||
  1559.     sscanf(StringToken, "%d", &Length) != 1)
  1560.     _IPParserAbort(IP_ERR_NUMBER_EXPECTED, StringToken);
  1561.  
  1562.     for (i = 0; i < Length; i++) {
  1563.     if (_IPGetToken(Handler, StringToken) != IP_TOKEN_OPEN_PAREN)
  1564.         _IPParserAbort(IP_ERR_OPEN_PAREN_EXPECTED, StringToken);
  1565.  
  1566.     V = IPAllocVertex(0, 0, NULL, NULL);
  1567.  
  1568.     /* The following handle the optional attributes in struct. */
  1569.     if (_IPGetToken(Handler, StringToken) == IP_TOKEN_OPEN_PAREN)
  1570.         GetVertexAttributes(V, Handler);
  1571.     else
  1572.         _IPUnGetToken(Handler, StringToken);
  1573.  
  1574.     for (j = 0; j < 3; j++)                /* Read coordinates. */
  1575.         GetNumericToken(Handler, &V -> Coord[j]);
  1576.  
  1577.     _IPGetCloseParenToken(Handler);
  1578.  
  1579.     if (VTail == NULL)
  1580.         PPolygon -> PVertex = VTail = V;
  1581.     else {
  1582.         VTail -> Pnext = V;
  1583.         VTail = V;
  1584.     }
  1585.     }
  1586.  
  1587.     if (_IritPrsrPolyListCirc && IsPolygon)
  1588.     VTail -> Pnext = PPolygon -> PVertex;
  1589.  
  1590.     _IPGetCloseParenToken(Handler);
  1591. }
  1592.  
  1593. /*****************************************************************************
  1594. * DESCRIPTION:                                                               M
  1595. * Concatenate all freeform objects in FreeForms into a single list.          M
  1596. *                                                                            *
  1597. * PARAMETERS:                                                                M
  1598. *   FreeForms:  Freeform geometry to process.                     M
  1599. *                                                                            *
  1600. * RETURN VALUE:                                                              M
  1601. *   IPObjectStruct *:   concatenated linked list.                            M
  1602. *                                                                            *
  1603. * KEYWORDS:                                                                  M
  1604. *   IritPrsrConcatFreeForm, conversion                                       M
  1605. *****************************************************************************/
  1606. IPObjectStruct *IritPrsrConcatFreeForm(IritPrsrFreeFormStruct *FreeForms)
  1607. {
  1608.     IPObjectStruct *ObjLast,
  1609.     *Objs = NULL,
  1610.     *CrvObjs = FreeForms -> CrvObjs,
  1611.     *SrfObjs = FreeForms -> SrfObjs,
  1612.     *TrimSrfObjs = FreeForms -> TrimSrfObjs,
  1613.     *TrivarObjs = FreeForms -> TrivarObjs;
  1614.  
  1615.     if (CrvObjs != NULL) {
  1616.     ObjLast = IritPrsrGetLastObj(CrvObjs);
  1617.     ObjLast -> Pnext = Objs;
  1618.     Objs = CrvObjs;
  1619.     }
  1620.     if (SrfObjs != NULL) {
  1621.     ObjLast = IritPrsrGetLastObj(SrfObjs);
  1622.     ObjLast -> Pnext = Objs;
  1623.     Objs = SrfObjs;
  1624.     }
  1625.     if (TrimSrfObjs != NULL) {
  1626.     ObjLast = IritPrsrGetLastObj(TrimSrfObjs);
  1627.     ObjLast -> Pnext = Objs;
  1628.     Objs = TrimSrfObjs;
  1629.     }
  1630.     if (TrivarObjs != NULL) {
  1631.     ObjLast = IritPrsrGetLastObj(TrivarObjs);
  1632.     ObjLast -> Pnext = Objs;
  1633.     Objs = TrivarObjs;
  1634.     }
  1635.  
  1636.     return Objs;
  1637. }
  1638.  
  1639. #ifdef DEBUG
  1640.  
  1641. /*****************************************************************************
  1642. * DESCRIPTION:                                                               *
  1643. *    Dummy function to link at debugging time.                               *
  1644. *                                                                            *
  1645. * PARAMETERS:                                                                *
  1646. *                                                                            *
  1647. * RETURN VALUE:                                                              *
  1648. *   void                                                                     *
  1649. *****************************************************************************/
  1650. void IritPrsrDbg(void)
  1651. {
  1652.     CagdDbg(NULL);
  1653.     TrimDbg(NULL);
  1654.     TrivDbg(NULL);
  1655.     IritPrsrStderrObject(NULL);
  1656. }
  1657.  
  1658. #endif /* DEBUG */
  1659.